<?php
/**
 * Created by PhpStorm.
 * User: zy-l
 * Date: 2019/6/19
 * Time: 10:31 PM
 */

namespace App\HttpController;


use App\Common\Exception\ApiException;
use App\Common\Exception\ThrowException;
use App\Model\AuthRule;
use Base\Throwable\HttpException;
use EasySwoole\Http\Message\Status;
use EasySwoole\Validate\Validate;

abstract class AdminBase extends Base
{
    protected $mid;       //操作者
    protected $is_root; //是否超管

    /**
     * 进行权限验证与登陆验证
     */
    public function _initialize()
    {

        $this->setModule('Admin'); //
        //判断是否有权限操作
    }

    /**
     * 配置可访问与禁止访问
     * @param $url
     * @return bool
     */
    public function accessControl($url)
    {

        $conf = \EasySwoole\EasySwoole\Config::getInstance()->getConf('AUTH_CONFIG');
        $allow = $conf['ALLOW_VISIT'];
        $deny = $conf['DENY_VISIT'];
        $check = strtolower($url);
        if (!empty($deny) && in_array_case($check, $deny)) {
            return false; //非超管禁止访问deny中的方法
        }

        if (!empty($allow) && in_array_case($check, $allow)) {

            return true;
        }
    }

    public function onRequest(?string $action): ?bool
    {
        $this->session()->start();
        //判断用户登陆
        if (!parent::onRequest($action)) {
            return false;  //用户网站关闭
        };
        $this->mid = is_login($this->session()->get('zy_auth'));
        $url = $this->getModule() . '/' . $this->getActionController() . '/' . $this->getActionName();
        $requset_suffix = \EasySwoole\EasySwoole\Config::getInstance()->getConf('requset_suffix');
        if (isset($requset_suffix)) {
            $url .= "." . $requset_suffix;
        }
        $this->is_root = is_administrator($this->mid);
        if (!$this->is_root) {
            //进行权限验证
            $access = $this->accessControl($url);
            if (false === $access) {
                throw  new  ApiException(ApiException::ERROR_ACCESS_NOT_ENABLE);
            } elseif (null === $access) {
                if(empty($this->mid)){
                    $this->redirect('/Admin/login/index');
                }
                //检测访问权限
                $rule = $url;
                if (!$this->checkRule($rule, array(1, 2))) {
                    throw  new  ApiException(ApiException::ERROR_UNAUTHORIZE_ACCESS);
                } else {
                    // 检测分类及内容有关的各项动态权限
                    $dynamic = $this->checkDynamic();
                    if (false === $dynamic) {
                        throw  new  ApiException(ApiException::ERROR_UNAUTHORIZE_ACCESS);
                    }
                }
            }

        }
        /*
         * 各个action的参数校验
         */
        $v = $this->getValidateRule($action);
        if ($v && !$this->validate($v)) {
            $this->writeJson($v->getError()->__toString(), ['errorCode' => 1, 'data' => []], 422, Status::CODE_OK);
            return false;
        }
        return true;
    }

    /**
     * 动态检测
     */
    protected function checkDynamic()
    {

    }

    public function checkRule($rule, $type = AuthRule::RULE_URL, $mode = 'url')
    {
        static $Auth = null;
        if (!$Auth) {
            $Auth = new \App\Common\Library\Auth();
        }
        if (!$Auth->check($rule, $this->mid, $type, $mode)) {
            return false;
        }
        return true;

    }


    /**
     * 头部取token
     * @return mixed
     * @throws ThrowException
     */
    private function getTokenByRequest()
    {
        if (!$this->request()->hasHeader('authorization')) {
            throw new ThrowException(ThrowException::ERROR_AUTHORIZATION);
        }
        $tokenInfo = explode(' ', $this->request()->getHeader('authorization')[0]);
        if (empty($tokenInfo[1]) || $tokenInfo[0] !== 'Bearer') {
            throw new ThrowException(ThrowException::ERROR_UNAUTHORIZE_ACCESS);

        }
        list($tokenType, $token) = $tokenInfo;
        return $token;
    }


    public function showHtmlError($msg)
    {
        $this->assign(['msg' => $msg]);
        return $this->fetch("../Error/msg");
    }

    abstract protected function getValidateRule(?string $action): ?Validate;

}